/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package pagrafo.genetico;

import java.util.ArrayList;
import java.util.Collections;

/**
 *
 * @author Fabricio
 */
public class Mutacao {
    
    /**
     * Método que aplica diversas mutações sobre 1 cromossomo para encontrar variações aleatórias melhores
     * @param c cromossomo a ser melhorado
     * @param n número de tentativas de variações
     * @param a número de variaçoes sobre uma variação
     * @return 
     */
    public static Cromossomo mutacaoMelhorDeN(Cromossomo c, int n, int a){
        
        ArrayList<Cromossomo> variacoes = new ArrayList<Cromossomo>();
        
        for(int i = 0; i < n ; i++){
            
            int v[] = c.getV().clone();
            
            for(int j = 0; j < a ; j++){
            
                int x,y;

                //Limites onde será feita a mutação
                int Min = 1;
                int Max = v.length - 2;

                //Executa até uma das condições de parada
                do {

                    x = (int) (Min + Math.random()*Max);
                    y = (int) (Min + Math.random()*Max);

                } while (
                        (v[x] == 0 && (v[x-1]==0 || v[x+1]==0))  || // x==0 e uma das proximidades de x também
                        (v[y] == 0 && (v[y-1]==0 || v[y+1]==0))  || // y==0 e uma das proximidades de y também
                        (v[x]==0 && v[y]==0 && Math.abs(x-y)==1) || // x==0 e y==0 e os dois estão próximos
                        (x == y)                                    // x e y são iguais
                        );

                //Faz mutação
                int aux = v[x];
                v[x] = v[y];        
                v[y] = aux;
                
                variacoes.add(new Cromossomo(c.getGrafo(), c.getK(), c.getCapacidade(), v));
            } 
        }
        
        int melhor = 0;
        double melhorScore = variacoes.get(0).getScore();
        
        for (int i = 1; i < variacoes.size(); i++) {
            if(variacoes.get(i).getScore() < melhorScore){
                melhorScore = variacoes.get(i).getScore();
                melhor = i;
            }
        }
        
        return variacoes.get(melhor);
    }
    
    /**
     * Método que aplica diversas mutações sobre 1 cromossomo para encontrar variações aleatórias melhores
     * @param c cromossomo a ser melhorado
     * @param n número de tentativas de variações
     * @param a número de variaçoes sobre uma variação
     * @return 
     */
    public static Cromossomo executar(Cromossomo c){
            
        int v[] = c.getV().clone();

        int x,y;

        //Limites onde será feita a mutação
        int Min = 1;
        int Max = v.length - 2;

        //Executa até uma das condições de parada
        do {

            x = (int) (Min + Math.random()*Max);
            y = (int) (Min + Math.random()*Max);

        } while (
                (v[x] == 0 && (v[x-1]==0 || v[x+1]==0))  || // x==0 e uma das proximidades de x também
                (v[y] == 0 && (v[y-1]==0 || v[y+1]==0))  || // y==0 e uma das proximidades de y também
                (v[x]==0 && v[y]==0 && Math.abs(x-y)==1) || // x==0 e y==0 e os dois estão próximos
                (x == y)                                    // x e y são iguais
                );

        //Faz mutação
        int aux = v[x];
        v[x] = v[y];        
        v[y] = aux;
        
        return new Cromossomo(c.getGrafo(), c.getK(), c.getCapacidade(), v);
    }
    
}
